﻿using System;
using System.Collections.Generic;
using System.Text;

using Atosenet.Protocol;

namespace Atosenet.Data
{
    public abstract class DataPacket
    {
        #region 成员



        #endregion


        #region 初始化

        public DataPacket(byte cmd)
        {
            CMD = cmd;
        }

        #endregion


        #region 公开函数


        #endregion


        #region 静态函数

        public static IProtocolPacket GenerateProtocolPacket(byte cmd, IADCode iad)
        {
            return GenerateProtocolPacket(cmd, iad, null);
        }

        public static IProtocolPacket GenerateProtocolPacket(byte cmd, IADCode iad, PacketPayload payload)
        {
            try
            {
                int count = 0;
                count += iad == IADCode.Empty ? 0 : IADCode.IAD_CODE_LENGTH;
                count += PacketPayload.IsNullOrInvalid(payload) ? 0 : payload.DataLength;
                byte[] data = new byte[count];

                if (iad != IADCode.Empty)
                {
                    byte[] tData = new byte[] { iad.IndustryCode, iad.ApplicationCode, iad.DataTypeCode };
                    Array.Copy(tData, 0, data, 0, tData.Length);
                }

                if (!PacketPayload.IsNullOrInvalid(payload))
                    Array.Copy(payload.RawData, 0, data, iad == IADCode.Empty ? 0 : IADCode.IAD_CODE_LENGTH, payload.DataLength);

                //return data.Length == 0 ? ProtocolPacket.CreatePacket(cmd) : ProtocolPacket.CreatePacket(cmd, data); 
                /* 构造DataPacket需要考虑ProtocoPacket类型 */
                return null;
            }
            catch
            {
                return null;
            }
        }

        //public static IADCode GetPacketIADCode(IProtocolPacket packet)
        //{
        //    return GetPacketIADCode(packet, true);
        //}

        //public static IADCode GetPacketIADCode(IProtocolPacket packet, bool ignoreErrors)
        //{
        //    if (!ignoreErrors && ProtocolPacket.IsNullOrInvalid(packet))
        //        return IADCode.Empty;

        //    if (packet.DATA.Length < IADCode.IAD_CODE_LENGTH)
        //        return IADCode.Empty;

        //    IADCode result = new IADCode(packet.DATA[0], packet.DATA[1], packet.DATA[2]);
        //    return result;
        //}

        public static byte[] CombineIADCodeWithContent(IADCode iad, byte[] content)
        {
            if (content == null)
                return new byte[] { iad.IndustryCode, iad.ApplicationCode, iad.DataTypeCode };

            try
            {
                byte[] result = new byte[content.Length + IADCode.IAD_CODE_LENGTH];
                result[0] = iad.IndustryCode;
                result[1] = iad.ApplicationCode;
                result[2] = iad.DataTypeCode;
                Array.Copy(content, 0, result, IADCode.IAD_CODE_LENGTH, content.Length);
                return result;
            }
            catch
            {
                return new byte[] { iad.IndustryCode, iad.ApplicationCode, iad.DataTypeCode };
            }
        }

        public static byte[] RemoveIADCodeFromContent(byte[] content)
        {
            if (content == null && content.Length < 3)
                return new byte[0];

            try
            {
                byte[] result = new byte[content.Length - IADCode.IAD_CODE_LENGTH];
                Array.Copy(content, IADCode.IAD_CODE_LENGTH, result, 0, result.Length);
                return result;
            }
            catch
            {
                return new byte[0];
            }
        }

        #endregion


        #region 核心函数

        public virtual bool Verify(IProtocolPacket packet)
        {
            return VerifyIADCode(packet) && VerifyPayload(packet);
        }

        protected bool VerifyIADCode(IProtocolPacket packet)
        {
            //IADCode current = GetPacketIADCode(packet);
            //return current == PacketIAD;

            return true;
        }

        protected abstract bool VerifyPayload(IProtocolPacket packet);

        #endregion


        #region 属性

        public PacketPayload Payload
        {
            get;
            protected set;
        }

        public abstract IADCode PacketIAD
        {
            get;
        }

        public byte CMD
        {
            get;
            private set;
        }

        public bool IsValid
        {
            get;
            protected set;
        }

        public abstract int DataLength
        {
            get;
        }

        #endregion
    }
}
